var gamerooms = {};
var gameusers = {};
var fs = require('fs');
var path = require('path');
var http = require('http');
var escape = require("html-escape");
var websocket = require('websocket');

var httpserver = http.createServer(function (request, response) {
        console.log((new Date()) + ' Received request for ' + request.url);
        if (request.method === "GET") {
            var filename = "." + request.url;
            if (request.url != '/' && fs.existsSync(filename)) {
                fs.readFile(filename, function (err, data) {
                    var extname = path.extname(filename);
                    if (extname === '.js') {
                        response.writeHead(200, { 'Content-Type': 'application/x-javascript' });
                        response.end(data);
                    } else if (extname === '.css') {
                        response.writeHead(200, { 'Content-Type': 'text/css; charset=utf-8' });
                        response.end(data);
                    } else if (extname === '.html') {
                        response.writeHead(200, { 'Content-Type': 'text/html' });
                        response.end(data);
                    } else if (extname === '.png') {
                        response.writeHead(200, { 'Content-Type': 'image/png' });
                        response.end(data);
                    } else if (extname === '.jpg') {
                        response.writeHead(200, { 'Content-Type': 'image/jpg' });
                        response.end(data);
                    } else if (extname === '.gif') {
                        response.writeHead(200, { 'Content-Type': 'image/gif' });
                        response.end(data);
                    } else {
                        response.writeHead(400);
                        response.end(data);
                    }
                });
            }
            else {
                if (request.url === "/") {
                    fs.readFile("./game-lobby.html", function (err, data) {
                        response.writeHead(200, { 'Content-Type': 'text/html' });
                        response.end(data);
                    });
                } else {
                    response.writeHead(404);
                    response.end();
                }
            }
        }
        else if (request.method === "POST") {
            request.on("data", function (chunk) {
                console.log((new Date()) + ' Received post data' + chunk + ' for ' + request.url);
                response.writeHead(500);
                response.end(error.toString());
            });
        } else {
            response.writeHead(404);
            response.end();
        }
    })
    ;

httpserver.listen(8000, function () {
    console.log((new Date()) + ' Server is listening on port 8000');
});

var websocketserver = new websocket.server({
    httpServer: httpserver,
    autoAcceptConnections: false
});

function doesUserIsAllowed(user) {
    return !gameusers[user];
}

websocketserver.on('request', function (request) {
    var user = request.resource.substring(1);
    if (!doesUserIsAllowed(user)) {
        console.log((new Date()) + ' Connection from ' + request.resource + ' rejected.');
        request.reject();
        return;
    }

    var connection = request.accept('echo-protocol', request.origin);
    console.log((new Date()) + ' Connection from ' + request.resource + ' accepted.');

    gameusers[user] = { name: user, conn: connection, room: null };

    sendMessageToEveryOne(JSON.stringify({command: "WL", user: user}));

    connection.on('close', function (reasonCode, description) {
        if (gameusers[user]) {
            try {
                var userroom = gameusers[user].room;
                if (userroom && gamerooms[userroom]) {
                    if (gamerooms[userroom].owner === user) {
                        sendMessageToEveryOne(JSON.stringify({command: "RM", user: user, data: userroom}));
                        for (var i = 0; i < gamerooms[userroom].members.length; i++) {
                            gameusers[gamerooms[userroom].members[i]].room = null;
                        }
                        delete gamerooms[userroom];
                    } else {
                        var index = gamerooms[userroom].members.indexOf(user);
                        if (index > -1) {
                            gamerooms[userroom].members.splice(index, 1);
                        }
                    }
                }
                delete gameusers[user];
                sendMessageToEveryOne(JSON.stringify({command: "Q", user: user}));
            } catch (error) {
                console.error(error.toString());
            }
        }
        console.log((new Date()) + ' Peer [' + user + ']' + connection.remoteAddress + ' disconnected.');
    });

    connection.on('message', function (message) {
        if (message.type === 'utf8') {
            try {
                console.log('Received Message: ' + message.utf8Data);
                var cmd = JSON.parse(message.utf8Data);
                cmd.user = escape(user);
                switch (cmd.command) {
                    case "UL":
                        cmd.code = 200;
                        cmd.data = getUserList();
                        connection.sendUTF(JSON.stringify(cmd));
                        break;
                    case "RL":
                        cmd.code = 200;
                        cmd.data = getRoomList();
                        connection.sendUTF(JSON.stringify(cmd));
                        break;
                    case "CR":
                        if (!gamerooms[cmd.data]) {
                            gamerooms[cmd.data] = { name: cmd.data, number: 4, owner: user, members: [user] };
                            cmd.code = 200;
                            gameusers[user].room = cmd.data;
                            cmd.data = gamerooms[cmd.data];
                            sendMessageToEveryOne(JSON.stringify(cmd));
                        } else {
                            cmd.code = 400;
                            cmd.message = "bad request";
                            connection.sendUTF(JSON.stringify(cmd));
                        }
                        break;
                    case "GR":
                        if (gamerooms[cmd.data]) {
                            cmd.code = 200;
                            cmd.data = gamerooms[cmd.data];
                            connection.sendUTF(JSON.stringify(cmd));
                        } else {
                            cmd.code = 404;
                            connection.sendUTF(JSON.stringify(cmd));
                        }
                        break;
                    case "ER":
                        if (gamerooms[cmd.data]) {
                            if (gamerooms[cmd.data].members.length >= gamerooms[cmd.data].number) {
                                cmd.code = 400;
                                cmd.message = "room is full";
                                connection.sendUTF(JSON.stringify(cmd));
                            } else {
                                if (gamerooms[cmd.data].members.indexOf(user) === -1) {
                                    if (gameusers[user] && gameusers[user].room) {
                                        sendMessageToEveryOne(JSON.stringify({command: "QR", user: user, data: gameusers[user].room}));
                                        gameusers[user].room = null;
                                    }
                                    gamerooms[cmd.data].members.push(user);
                                    gameusers[user].room = cmd.data;
                                    cmd.code = 200;
                                    sendMessageToEveryOne(JSON.stringify(cmd));
                                } else {
                                    cmd.code = 400;
                                    cmd.message = "user has already in room";
                                    connection.sendUTF(JSON.stringify(cmd));
                                }
                            }
                        } else {
                            cmd.code = 400;
                            cmd.message = "room does not exits";
                            connection.sendUTF(JSON.stringify(cmd));
                        }
                        break;
                    case "QR":
                        if (gamerooms[cmd.data]) {
                            var index = gamerooms[cmd.data].members.indexOf(user);
                            if (index > -1) {
                                gamerooms[cmd.data].members.splice(index, 1);
                                cmd.code = 200;
                                sendMessageToEveryOne(JSON.stringify(cmd));
                            } else {
                                cmd.code = 400;
                                cmd.message = "user does not in room";
                                connection.sendUTF(JSON.stringify(cmd));
                            }
                        } else {
                            cmd.code = 400;
                            cmd.message = "room does not exits";
                            connection.sendUTF(JSON.stringify(cmd));
                        }
                        break;
                    case "PM":
                        if (gameusers[user].room) {
                            cmd.code = 200;
                            cmd.data = escape(cmd.data);
                            sendMessageToEveryOneInRoom(gameusers[user].room, JSON.stringify(cmd));
                        } else {
                            cmd.code = 400;
                            cmd.message = "user does not in any room";
                            connection.sendUTF(JSON.stringify(cmd));
                        }
                        break;
                    case "PMU":
                        if (gameusers[cmd.data.user]) {
                            cmd.code = 200;
                            cmd.data.message = escape(cmd.data.message);
                            gameusers[cmd.data.user].conn.sendUTF(JSON.stringify(cmd));
                        } else {
                            cmd.code = 400;
                            cmd.message = "user does not exits";
                            connection.sendUTF(JSON.stringify(cmd));
                        }
                        break;
                    case "SG":
                        var userroom = gameusers[user].room;
                        if (userroom) {
                            cmd.code = 200;
							cmd.data=gamerooms[cmd.data];
                            sendMessageToEveryOneInRoom(userroom, JSON.stringify(cmd));
                        } else {
                            cmd.code = 400;
                            cmd.message = "user does not in any room";
                            connection.sendUTF(JSON.stringify(cmd));
                        }
                        break;
                    case "Q":
                        connection.close();
                        break;
					case "GA":
					 var userroom = gameusers[user].room;
                     if (userroom) {
						 cmd.code = 200;
						 sendMessageToEveryOneInRoom(userroom,JSON.stringify(cmd));
					 }
					 break;
                    default:
                        console.log("no match command");
                        break;
                }
            } catch (error) {
                console.error(error.toString());
            }
        }
    });
})
;

function getRoomList() {
    var rooms = [];
    for (var room in gamerooms) {
        rooms.push({ name: room, number: gamerooms[room].number, members: gamerooms[room].members });
    }
    return rooms;
}

function getUserList() {
    var users = [];
    for (var user in gameusers) {
        users.push({ name: user, room: gameusers[user].room });
    }
    return users;
}

function sendMessageToEveryOneInRoom(room, message) {
    for (var i = 0; i < gamerooms[room].members.length; i++) {
        var user = gamerooms[room].members[i];
        var conn = gameusers[user].conn;
        if (conn) {
            conn.sendUTF(message);
        }
    }
}

function sendMessageToEveryOne(message) {
    for (var user in gameusers) {
        var conn = gameusers[user].conn;
        if (conn) {
            conn.sendUTF(message);
        }
    }
}